import moment from 'moment'
/**
 * User: zeng/7047729872@qq.com
 * Date: 2018/5/29
 * Time: 16:50
 */
function date(date, fmt) {
    if (!date) return '';
    let d = moment(date).format(fmt);
    return ~d.indexOf('Invalid') ? '' : d;
}


const excel = {
  exportsData: [], // 导出的数据
  options: { // 其他参数
    title: '荣者地产', // 文件标题
    header: [],
  }
};

/**
 * 校验属性
 * @param value 被校验的值
 * @param type 校验类型
 * @returns {boolean} 有无效
 */
function checkAttr(value, type = 'array') {
  if (!value) return false;
  if (type.toLowerCase() === 'array') {
    // 数组
    return Array.isArray(value) && value.length;
  }
  return false;
}

/**
 * 对象深拷贝
 * @param value 拷贝的值
 * @returns {*}
 */
function deepCopy(value) {
  if (!value) return value;
  return JSON.parse(JSON.stringify(value));
}

/**
 * @description 根据字段获取对象
 * @param arr {Array} 待处理的数组
 * @param val {*} 跟数组中的元素进行匹配的值
 * @param filed {*} 跟数组中的元素进行匹配的字段
 * @returns {*} 返回找到的数组值
 */
function getObjByFiled(arr, val, filed) {
  let o = {};
  if (!(val && filed)) return o;
  o = Array.isArray(arr) && arr.find((current) => {
    return current[filed] === val;
  });
  return o ? o : {};
}

/**
 * 导出Excel
 * @param data 导出的数据格式
 * @param title 导出的文件名
 * @param header 导出的表格字段 ->> {label: '', value: ''} label 是标题，value 是数据中对应的值
 */
export function exports({data, title, header} = {}) {
  if (!(checkAttr(data) && checkAttr(header))) {
    throw new Error('因数据问题，无法正确执行导出程序，请检查导出的数据是否有效。');
  }

  const op = excel.options;
  op.header = header;
  excel.exportsData = deepCopy(data);
  title && (op.title = title);

  (() => {
    let that = excel
      , op = excel.options
    ;
    require.ensure([], () => {
      const {export_json_to_excel} = require('./lib/Export2Excel');
      const tHeader = filterArrByElType(op.header, 'label');
      const list = that.exportsData;
      const data = formatJson(op.header, list);
      export_json_to_excel(tHeader, data, op.title);// 导出的表格名称，根据需要自己命名
    });

    /**
     * 数据格式化
     * @param filterVal 过滤的值
     * @param jsonData JSON数据
     */
    function formatJson(filterVal, jsonData) {
      return jsonData.map(v => {
        for (let attr in v) {
          let el = {}; // 记录需要处理的属性
          // 得到header对象
          filterVal.some((current) => {
            if (current.value === attr) {
              el = current;
              return true;
            }
          });
          // 判断header对象是否拥有type值
          if (el && el.hasOwnProperty('type')) {
            const type = el.type;
            // 时间
            type === 'date' && (v[el.value] = date(v[el.value], el.format || 'YYYY-MM-DD HH:mm:ss'));
            // 状态
            type === 'status' && (v[el.value] = getObjByFiled(el.options, v[el.value], 'value').label || '');
          }
        }
        filterVal = filterArrByHidden(filterVal);
        return filterVal.map(j => v[j.value]);
      })
    }

    /**
     * 将属性值从数组中提出来单独作为一个数组
     *
     * @param arr 数组
     * @param type 属性
     * @returns {Uint8Array | any[] | Int32Array | Uint16Array | Uint32Array | Float64Array | any}
     */
    function filterArrByElType(arr, type) {
      arr = filterArrByHidden(arr);
      return arr.map((current) => {
        return current[type];
      })
    }

    /**
     * 过滤数组，根据是否包含了hidden属性为准
     * @param arr 过滤后的数组
     */
    function filterArrByHidden(arr) {
      return arr.filter((current) => {
        if (!current.hasOwnProperty('hidden')) {
          return current;
        }
      });
    }
  })();
}

/**
 * 导入
 *  <p> 如果有一个字段，在所有的数据中都没有值，那么就会无视该字段 </p>
 *  <b> 导入的数据在表格字段中没有，并且字段类型也不属于'hidden'的，则拒绝导入 </b>
 * @param data 需要导入的数据
 * @param title null
 * @param header 导入后的表格格式
 */
export function imports({/*data, title,*/ header} = {}) {
  const that = this;
  FileReader.prototype.readAsBinaryString = function (data) {
    let filterArr = [] // 最终处理后进行复制的数据
      , binary = ''
      , rABS = false //是否将文件读取为二进制字符串
      , wb = {} //读取完成的数据
      , outdata = [] // 导入的数据
      , reader = new FileReader()
    ;
    reader.onload = function () {
      let bytes = new Uint8Array(reader.result);
      for (let i = 0, length = bytes.byteLength; i < length; i++) {
        binary += String.fromCharCode(bytes[i]);
      }
      let XLSX = require('xlsx');
      if (!XLSX) throw new Error('请在命令行输入 ->> [npm install -S file-saver xlsx && npm install -D script-loader]');
      wb = rABS
        ? XLSX.read(btoa(binary), { //手动转化
          type: 'base64'
        })
        : XLSX.read(binary, {
          type: 'binary'
        })
      ;

      // 拿到导入数据
      outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);

      if (checkAttr(outdata)) {
        let isAdd = outdata.every((current, index) => {
          let outdataKey = Object.keys(outdata[index]) // 表头
            , oIndex = 0 // 索引
            , hasExit // 导入的数据是否存在header中
            , errorField = ''
          ;
          // 3.当前数据是否符合格式
          hasExit = outdataKey.every((current) => {
            oIndex = header.findIndex((_current) => {
              return current === _current.label;
            });
            let b = oIndex !== -1;
            !b && (errorField = current);
            return b;
          });
          if (hasExit) {
            // 4.0 符合
            filterArr[index] = {};
            // 5 进行最后的数据处理工作
            hasExit = header.every((_current) => {
              if (!_current.hasOwnProperty('hidden')) {
                filterArr[index][_current.value] = current[_current.label];
                // 数据格式还原
                if (_current.hasOwnProperty('type')) {
                  _current.type === 'date' && current[_current.label]
                  && (filterArr[index][_current.value] = new Date(current[_current.label]));
                  if (_current.type === 'status' && _current.value) {
                    try {
                      filterArr[index][_current.value] = getObjByFiled(_current.options, current[_current.label], 'label').value || '';
                    } catch ({message}) {
                      that.$message.error(message);
                      return false;
                    }
                  }
                }
              }
              return true;
            })
          } else {
            that.$message.error('导入的格式不正确：' + errorField);
          }
          return hasExit;
        });
        isAdd && (that.ex.importData = filterArr)
      }
    };
    reader.readAsArrayBuffer(data);
  };
}
